<?php

/**
 * Synonym model
 */
class SynonymModel extends CFormModel
{
	public $word;
	public $synonym;
	public $file;

	/**
	 * @var XS
	 */
	private $_xs;

	/**
	 * @param mixed $xs
	 * @throws CHttpException
	 */
	public function __construct($xs)
	{
		try {
			$this->_xs = is_string($xs) ? Yii::app()->pf->get($xs) : $xs;
			parent::__construct('add');
		} catch (XSException $e) {
			throw new CHttpException(500, $e->getMessage());
		}
	}

	/**
	 * Declares the validation rules.
	 */
	public function rules()
	{
		return array(
			array('word, synonym', 'required', 'on' => 'add'),
			array('file', 'file', 'on' => 'import', 'types' => array('txt', 'csv')),
		);
	}

	public function attributeLabels()
	{
		return array(
			'word' => '原词',
			'synonym' => '同义词',
			'file' => 'CSV 文件',
		);
	}

	public function getIsRemoved()
	{
		return $this->hasRemovedCache();
	}

	public function findAll($limit = 0, $offset = 0)
	{
		$ret = array();
		if ($limit === 0) {
			$limit = CPagination::DEFAULT_PAGE_SIZE;
		}
		foreach ($this->_xs->search->getAllSynonyms($limit, $offset) as $word => $synonyms) {
			foreach ($synonyms as $synonym) {
				$ret[] = array(
					'word' => $word,
					'synonym' => $synonym,
					'isRemoved' => $this->hasRemovedCache($word, $synonym),
				);
			}
		}
		return $ret;
	}

	public function delete()
	{
		$index = $this->_xs->index;
		$index->delSynonym($this->word, $this->synonym);
		$index->flushIndex();
		$this->addRemovedCache();
	}

	public function save()
	{
		if ($this->validate()) {
			$index = $this->_xs->index;
			$index->addSynonym($this->word, $this->synonym);
			$index->flushIndex();
			$this->delRemovedCache();
			return true;
		}
		return false;
	}

	/**
	 * Import words from file
	 */
	public function import()
	{
		$this->setScenario('import');
		if (!$this->validate()) {
			return false;
		}
		$file = CUploadedFile::getInstance($this, 'file');
		if (($fd = @fopen($file->tempName, 'r')) === false) {
			$this->addError('file', '无法读取上传的临时文件');
			return false;
		}
		$index = $this->_xs->index; /* @var $index XSIndex */
		$index->openBuffer();
		while (($row = fgetcsv($fd)) !== false) {
			if (count($row) !== 2) {
				continue;
			}
			$index->addSynonym($row[0], $row[1]);
		}
		$index->closeBuffer();
		$index->flushIndex();
		$this->cleanRemovedCache();
		fclose($fd);
		return true;
	}

	protected function cleanRemovedCache()
	{
		if (($cache = Yii::app()->cache) !== null) {
			$key = $this->getRemovedCacheKey();
			if (($data = $cache->get($key)) !== false) {
				$cache->delete($key);
			}
		}
	}

	protected function addRemovedCache($word = null, $synonym = null)
	{
		if (($cache = Yii::app()->cache) !== null) {
			$id = $this->getRemovedId($word, $synonym);
			$key = $this->getRemovedCacheKey();
			if (($data = $cache->get($key)) === false) {
				$data = array();
			}
			$data[$id] = true;
			$cache->set($key, $data, 1800);
		}
	}

	protected function delRemovedCache($word = null, $synonym = null)
	{
		if (($cache = Yii::app()->cache) !== null) {
			$id = $this->getRemovedId($word, $synonym);
			$key = $this->getRemovedCacheKey();
			if (($data = $cache->get($key)) !== false && isset($data[$id])) {
				unset($data[$id]);
				$cache->set($key, $data, 1800);
			}
		}
	}

	protected function hasRemovedCache($word = null, $synonym = null)
	{
		if (($cache = Yii::app()->cache) !== null) {
			$id = $this->getRemovedId($word, $synonym);
			$key = $this->getRemovedCacheKey();
			if (($data = $cache->get($key)) !== false && isset($data[$id])) {
				return true;
			}
		}
		return false;
	}

	/**
	 * @return cache key
	 */
	private function getRemovedCacheKey()
	{
		return $this->_xs->getName() . '.' . get_class($this) . '.removed';
	}

	private function getRemovedId($word = null, $synonym = null)
	{
		if ($word === null) {
			$word = $this->word;
			$synonym = $this->synonym;
		}
		return md5($word . '|~|' . $synonym);
	}
}
